﻿import re
import sys
import os
import codecs

str_annotation_line = 'zhengwb_annotation_line'
str_annotation_tail = 'zhengwb_annotation_tail'
loop_num_max = 100

regex_find_annotation = re.compile(r'^\s*(#+.*)')
regex_find_kv = re.compile(r'^\s*([^#\s{}="]+)|^\s*("[^"]*")')     # 还需找 "   " 这种
regex_find_equals = re.compile(r'^\s*(=+)')
regex_find_lbrace = re.compile(r'^\s*({+)')
regex_find_rbrace = re.compile(r'^\s*(}+)')
regex_check_blank_line = re.compile(r'^\s*(\S+)')
regex_find_key_markable = re.compile(r'^\s*"[^"]*"$')
regex_find_value_markable = re.compile(r'^\s*(?="[^"]*"$|-{0,1}\d+|-{0,1}\d+\.+\d+$)')
regex_find_yes = re.compile(r'^\s*("yes"$)');
regex_find_no = re.compile(r'^\s*("no"$)');

regex_find_annotation_line = re.compile(str_annotation_line)
regex_find_annotation_tail = re.compile(str_annotation_tail)

g_list_key = []
g_list_value = []
list_working_key = g_list_key
stack_key_list = [g_list_key]

str_First_key = ''
str_Temp_key = ''
bHaveValue = False  # KV置True {置False
bHaveEqual = False  # =置True {置False
bHaveLeftBrace = False
bNextArray = False  # append时置True {置False

def DefaultParameter():
    global str_First_key
    global str_Temp_key
    global bHaveValue
    global bHaveEqual
    global bHaveLeftBrace
    global bNextArray

    str_First_key = ''
    str_Temp_key = ''
    bHaveValue = False
    bHaveEqual = False
    bHaveLeftBrace = False
    bNextArray = False

def IsLineBlank(str):
    if regex_check_blank_line.search(str):
        return False
    else:
        return True

def ReplaceAnnotationLine(match):
    global list_working_key
    global g_list_value

    list_working_key.append(str_annotation_line)
    g_list_value.append(match.group(1))
    return ''

def ReplaceAnnotationTail(match):
    global list_working_key
    global g_list_value

    list_working_key.append(str_annotation_tail)
    g_list_value.append(match.group(1))
    return ''

def ReplaceKV(match):
    global str_First_key
    global str_Temp_key
    global bHaveValue
    global bHaveEqual
    global bHaveLeftBrace
    global bNextArray
    global stack_key_list
    global list_working_key
    global g_list_value
    
    myMatch = match.group(1)
    if myMatch == None:
        myMatch = match.group(2)
    bHaveValue = True
    if str_First_key == '':
        str_First_key = myMatch
    elif not bHaveLeftBrace:
        # K = V
        list_working_key.append(str_First_key)
        g_list_value.append(myMatch)
        DefaultParameter()
    elif str_Temp_key == '':
        str_Temp_key = myMatch
    elif bHaveEqual:    # 第二个等号
        # K = { K = V }
        list_working_key.append(str_First_key)
        stack_key_list.append([str_Temp_key])
        temp_list = stack_key_list[len(stack_key_list) - 1]
        list_working_key.append(temp_list)
        list_working_key = temp_list
        g_list_value.append(myMatch)

        DefaultParameter()
    elif not bHaveEqual:
        # Array
        if bNextArray:
            if not isinstance(g_list_value[len(g_list_value) - 1], list):
                os.system('pause')
                sys.exit(1)
            g_list_value[len(g_list_value) - 1].append(myMatch)
        else:
            list_working_key.append(str_First_key)
            g_list_value.append([str_Temp_key, myMatch])
            bNextArray = True
    else:
        os.system('pause')
        sys.exit(1)

def ReplaceEquals(match):
    global bHaveEqual
    
    bHaveEqual = True
    return ''

def ReplaceLeftBrace(match):
    global str_First_key
    global str_Temp_key
    global bHaveValue
    global bHaveEqual
    global bHaveLeftBrace
    global bNextArray
    global stack_key_list
    global list_working_key

    if str_First_key != '' and str_Temp_key != '':
        # K = { K = {
        bHaveAnnotationFront = False
        if len(list_working_key) > 0 and list_working_key[len(list_working_key) - 1] == str_annotation_line:
            # 颠倒一下注释位置 还是会有问题 比如有两行注释 或 本身注释就不需要颠倒
            bHaveAnnotationFront = True
            list_working_key.pop()
        list_working_key.append(str_First_key)
        stack_key_list.append([])
        temp_list = stack_key_list[len(stack_key_list) - 1]
        list_working_key.append(temp_list)
        list_working_key = temp_list
        
        str_First_key = str_Temp_key
        str_Temp_key = ''

        if bHaveAnnotationFront:
            list_working_key.append(str_annotation_line)

    bNextArray = False
    bHaveEqual = False
    bHaveValue = False
    bHaveLeftBrace = True
    return ''

def ReplaceRightBrace(match):
    global str_First_key
    global str_Temp_key
    global bHaveValue
    global bNextArray
    global stack_key_list
    global list_working_key
    global g_list_value

    if str_First_key != '':
        if not bHaveValue:
            # K = {}
            list_working_key.append(str_First_key)
            g_list_value.append('')
            DefaultParameter()
            return ''
        elif bNextArray:
            # K = { V1, V2, ... }
            DefaultParameter()
            return ''
        elif str_Temp_key != '':
            # K = { V }
            list_working_key.append(str_First_key)
            g_list_value.append([str_Temp_key])
            DefaultParameter()
            return ''
    if len(stack_key_list) < 2:
        os.system('pause')
        sys.exit(1)
    stack_key_list.pop()
    list_working_key = stack_key_list[len(stack_key_list) - 1]
    DefaultParameter()
    return ''

def MatchLoop(str):
    str = regex_find_annotation.sub(ReplaceAnnotationLine, str, 1)
    if IsLineBlank(str):
        return str
    str = regex_find_kv.sub(ReplaceKV, str, 1)
    if IsLineBlank(str):
        return str
    str = regex_find_equals.sub(ReplaceEquals, str, 1)
    if IsLineBlank(str):
        return str
    str = regex_find_kv.sub(ReplaceKV, str, 1)
    if IsLineBlank(str):
        return str
    str = regex_find_lbrace.sub(ReplaceLeftBrace, str, 1)
    if IsLineBlank(str):
        return str
    str = regex_find_rbrace.sub(ReplaceRightBrace, str, 1)
    if IsLineBlank(str):
        return str
    str = regex_find_annotation.sub(ReplaceAnnotationTail, str, 1)
    return str

def TraverseArray(value_list):
    if not isinstance(value_list, list):
        os.system('pause')
        sys.exit(1)
    strOut = ''
    index = 0
    for value in value_list:
        index = index + 1
        strTemp = value
        if not regex_find_value_markable.search(strTemp):
            strTemp =  regex_check_blank_line.sub("".join(['"', r'\1', '"']), strTemp)
        strTemp = regex_find_yes.sub('true', strTemp)
        strTemp = regex_find_no.sub('false', strTemp)

        if index < len(value_list):
            strOut = "".join([strOut, ' ', strTemp, ','])
        else:
            strOut = "".join([strOut, ' ', strTemp, ' ]'])
    return strOut

def TraverseAllKV(key_list, value_list, indent, output):
    index = 0
    indent_key = indent + 1

    for key in key_list:
        index = index + 1
        
        next_key = ''
        if index < len(key_list):
            next_key = key_list[index]

        if isinstance(key, list):
            TraverseAllKV(key, value_list, indent_key, output)
        elif regex_find_annotation_line.search(key):
            output.write("".join(['\n', '\t' * indent_key, value_list[0]]))
            del value_list[0]
            if '' == next_key:
                output.write("".join(['\n', '\t' * (indent_key - 1), '}']))
            continue
        elif regex_find_annotation_tail.search(key):
            output.write('\t' + value_list[0])
            del value_list[0]
            if '' == next_key:
                output.write("".join(['\n', '\t' * (indent_key - 1), '}']))
            continue
        else:
            key_temp = key
            if not regex_find_key_markable.search(key_temp):
                key_temp = regex_check_blank_line.sub("".join(['"', r'\1', '"']), key_temp)

            if next_key != '' and isinstance(next_key, list):
                output.write("".join(['\n', '\t' * indent_key, key_temp, ' : {']))
                continue
            elif value_list[0] == '':
                output.write("".join(['\n', '\t' * indent_key, key_temp, ' : {\n', '\t' * indent_key, '}']))
                del value_list[0]
            elif isinstance(value_list[0], list):
                output.write("".join(['\n', '\t' * indent_key, key_temp, ' : [', TraverseArray(value_list[0])]))
                del value_list[0]
            else:
                value_temp = value_list[0]
                if not regex_find_value_markable.search(value_temp):
                   value_temp =  regex_check_blank_line.sub("".join(['"', r'\1', '"']), value_temp)
                value_temp = regex_find_yes.sub('true', value_temp)
                value_temp = regex_find_no.sub('false', value_temp)
                output.write("".join(['\n', '\t' * indent_key, key_temp, ' : ', value_temp]))
                del value_list[0]
        # 判断是不是最末行 需要把注释段落的key删除掉
        IsTailKey = IsTheTailKey(index, key_list)
        if 1 == IsTailKey:
            output.write("".join(['\n', '\t' * (indent_key - 1), '}']))
        elif 0 == IsTailKey:
            output.write(',')
        #elif 2 == IsTailKey:  后面都是注释 在注释处理处处理            

def IsTheTailKey(index, key_list):
    if index >= len(key_list):
        return 1
    else:
        for num in range(index, len(key_list)):     # 不会到len(key_list) 所以安全
            if isinstance(key_list[num], list):
                return 0
            elif regex_find_annotation_line.search(key_list[num]) or regex_find_annotation_tail.search(key_list[num]):
                continue
            else:
                return 0
    return 2    # 后面都是注释语句

def main():
    print("##############################################\n在vs的py项目中能运行 在cmd中运行会显示编码问题\n##############################################\n注意转换前转换后的文件是否是utf-8编码\n#####################################\n确认放置位置\n#######################################################\n此py文件将会遍历文件夹下所有txt文件，将其转化为Json格式\n#######################################################\n原文件会改名为.bak后缀\n######################")
    os.system('pause')
    for root, dirs, files in os.walk(os.getcwd(), topdown=False):
        for name in files:
            if name[-3:] == 'txt':
                source_path = root + '\\' + name
                bak_path = source_path + '.bak'
                file = open(source_path, 'r', encoding="utf8")
                file_bak = open(bak_path, 'w', encoding="utf8")
                file_bak.write("".join(file.readlines()))
                file.close()
                file_bak.close()

                file = open(source_path, 'r', encoding="utf8")
                for line in file:
                    str_working_text = line
                    if IsLineBlank(str_working_text):
                        continue
                    match_line = regex_find_annotation_line.search(str_working_text)
                    match_tail = regex_find_annotation_tail.search(str_working_text)
                    if match_line or match_tail:
                        os.system('pause')
                        sys.exit(1)
                    
                    loop_num = 0
                    while not IsLineBlank(str_working_text):
                        loop_num = loop_num + 1
                        str_working_text = MatchLoop(str_working_text)
                        if loop_num >= loop_num_max:
                            os.system('pause')
                            sys.exit(1)
                file.close()

                file = open(source_path, 'w', encoding="utf8")
                file.write('{')
                TraverseAllKV(g_list_key, g_list_value, 0, file)
                file.close()
                
                g_list_key.clear()
                g_list_value.clear()
                list_working_key = g_list_key
                stack_key_list = [g_list_key]
                DefaultParameter()

                print('"', source_path, '" Has Transformed!')

if __name__ == '__main__':
    main()